<template>
  <div>
    <!-- 通过浏览器所暴露出来的统一接口，由用户主动授权发起来访问文件动作 -->
    <input
      type="file"
      ref="fileInput"
      :style="{ display: 'none' }"
      @change.prevent.stop="handleChange"
    />
    <div @click.stop="triggerUpload" v-bind="$attrs">
      <!-- 正在上传状态 -->
      <slot name="uploading" v-if="uploadStatus === 'uploading'">
        <button class="btn btn-primary">正在上传中</button>
      </slot>
      <!-- 上传成功状态 -->
      <slot
        name="uploading-success"
        v-else-if="uploadStatus === 'success'"
        :uploadData="uploadData"
      >
      </slot>
      <!-- 上传失败状态 -->
      <slot name="upload-error" v-else-if="uploadStatus === 'error'">
        <button class="btn btn-primary">上传失败</button>
      </slot>
      <!-- 未上传状态 -->
      <slot v-else>
        <button class="btn btn-primary">点击上传</button>
      </slot>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, PropType } from "vue";
import axios from "@/api/axios";
type UploadStatus = "success" | "error" | "uploading" | "ready";
export type CheckFunc = (file: File) => boolean;
export default defineComponent({
  props: {
    // 上传的地址
    action: {
      type: String,
      required: true,
    },
    // 添加上传前的操作, 验证
    beforeUpload: {
      type: Function as PropType<CheckFunc>,
    },
  },
  inheritAttrs: false,
  emits: ["uploadSuccess", "uploadError"],
  setup(props, context) {
    const uploadStatus = ref<UploadStatus>("ready");
    const fileInput = ref<null | HTMLInputElement>(null);
    const uploadData = ref();

    const triggerUpload = () => {
      const uploadClickStatus = ["ready", "error"];
      /* 点击选择文件 */
      if (
        fileInput.value &&
        uploadClickStatus.indexOf(uploadStatus.value) !== -1
      ) {
        fileInput.value.click();
      }
    };

    /* 选择文件发生改变时 */
    const handleChange = (e: Event) => {
      const currentTarget = e.target as HTMLInputElement;
      if (currentTarget.files) {
        const files = Array.from(currentTarget.files);
        if (props.beforeUpload) {
          const result = props.beforeUpload(files[0]);
          if (!result) return;
        }
        const formData = new FormData();
        formData.append("file", files[0]);
        uploadStatus.value = "uploading";
        // 发送请求
        axios
          .post(props.action, formData, {
            headers: {
              "Content-Type": "multipart/form-data",
            },
          })
          .then(
            (resp) => {
              // 先执行这句代码，再执行后面的
              context.emit("uploadSuccess", resp.data.data);
              // slot 传输数据
              uploadData.value = resp.data.data;
              uploadStatus.value = "success";
            },
            (e) => {
              context.emit("uploadError", { error: e });
              uploadStatus.value = "error";
            }
          )
          .finally(() => {
            if (fileInput.value) {
              fileInput.value.value = "";
            }
          });
      }
    };
    return {
      fileInput,
      uploadStatus,
      triggerUpload,
      handleChange,
      uploadData,
    };
  },
});
</script>
<style lang="scss" scoped>
// .upload {
//   text-align: center;
// }
// .upload-success {
//   display: block;

// }
// .upload-container {
//   display: flex;
//   align-items: center;
//   justify-content: center;
//   color: #ccc;
//   border: 1px dashed #ccc;
//   cursor: pointer;、
// }
</style>
